#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]

use std::process::{Command, Stdio};
use std::sync::Arc;
use tauri::{Manager, State, Window};
use rusqlite::{Connection, Result};
use serde::{Deserialize, Serialize};
use std::io::{BufRead, BufReader};
use chrono::Utc;
use regex::Regex;

// 定义包信息结构体
#[derive(Debug, Deserialize, Serialize)]
struct PackageInfo {
    name: String,
    version: String,
}

// 定义操作日志结构体
#[derive(Debug, Deserialize, Serialize)]
struct OperationLog {
    id: i32,
    timestamp: String,
    operation_type: String,
    package_spec: String,
    command: String,
    success: bool,
    output: String,
    error_message: String,
}

// 数据库连接管理器
struct DbConnection(Arc<Connection>);

// 初始化数据库表结构
fn init_database() -> Result<Connection> {
    // 获取应用数据目录
    let app_data_dir = tauri::api::path::app_data_dir(&Default::default())
        .expect("Failed to get app data directory");
    let db_path = app_data_dir.join("py_library_manager.db");
    let conn = Connection::open(db_path)?;
    
    // 创建操作日志表
    conn.execute(
        "CREATE TABLE IF NOT EXISTS operation_logs (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
            operation_type TEXT NOT NULL,
            package_spec TEXT NOT NULL,
            command TEXT NOT NULL,
            success BOOLEAN NOT NULL,
            output TEXT,
            error_message TEXT
        )",
        [],
    )?;
    
    // 创建设置表
    conn.execute(
        "CREATE TABLE IF NOT EXISTS settings (
            key TEXT PRIMARY KEY,
            value TEXT
        )",
        [],
    )?;
    
    Ok(conn)
}

// 记录操作日志
fn log_operation(
    conn: &Connection,
    operation_type: &str,
    package_spec: &str,
    command: &str,
    success: bool,
    output: &str,
    error_message: &str,
) -> Result<()> {
    let timestamp = Utc::now().format("%Y-%m-%d %H:%M:%S").to_string();
    
    conn.execute(
        "INSERT INTO operation_logs (timestamp, operation_type, package_spec, command, success, output, error_message) 
         VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)",
        &[&timestamp, &operation_type, &package_spec, &command, &success, &output, &error_message],
    )?;
    
    Ok(())
}

// 获取已安装的包列表
#[tauri::command]
fn get_installed_packages() -> Result<Vec<PackageInfo>, String> {
    // 执行pip list --format=json命令
    let output = Command::new("pip")
        .arg("list")
        .arg("--format=json")
        .stdout(Stdio::piped())
        .stderr(Stdio::piped())
        .output()
        .map_err(|e| format!("Failed to execute pip: {}", e))?;
    
    if !output.status.success() {
        let err_msg = String::from_utf8_lossy(&output.stderr).to_string();
        return Err(format!("Pip command failed: {}", err_msg));
    }
    
    // 解析JSON输出
    let packages: Vec<PackageInfo> = serde_json::from_slice(&output.stdout)
        .map_err(|e| format!("Failed to parse pip output: {}", e))?;
    
    Ok(packages)
}

// 执行pip命令
#[tauri::command]
fn run_pip_command(
    window: Window,
    operation_type: String,
    package_spec: String,
    db: State<'_, DbConnection>,
) -> Result<String, String> {
    let (mut command, full_command) = match operation_type.as_str() {
        "install" => {
            let mut cmd = Command::new("pip");
            cmd.arg("install").arg(&package_spec);
            let full_cmd = format!("pip install {}", package_spec);
            (cmd, full_cmd)
        },
        "uninstall" => {
            let mut cmd = Command::new("pip");
            cmd.arg("uninstall").arg(&package_spec).arg("-y");
            let full_cmd = format!("pip uninstall {} -y", package_spec);
            (cmd, full_cmd)
        },
        "update" => {
            let mut cmd = Command::new("pip");
            cmd.arg("install").arg("-U").arg(&package_spec);
            let full_cmd = format!("pip install -U {}", package_spec);
            (cmd, full_cmd)
        },
        _ => {
            return Err(format!("Unsupported operation type: {}", operation_type));
        }
    };
    
    // 设置命令的标准输出和标准错误流
    command.stdout(Stdio::piped());
    command.stderr(Stdio::piped());
    
    // 启动命令
    let mut child = command.spawn().map_err(|e| format!("Failed to start command: {}", e))?;
    
    // 创建输出缓冲区
    let mut output_lines = Vec::new();
    let mut error_message = String::new();
    
    // 读取标准输出和标准错误
    if let Some(stdout) = child.stdout.take() {
        let reader = BufReader::new(stdout);
        for line in reader.lines() {
            if let Ok(line_content) = line {
                output_lines.push(line_content.clone());
                // 发送进度事件到前端
                window.emit_all("pip-progress", &line_content).unwrap();
            }
        }
    }
    
    if let Some(stderr) = child.stderr.take() {
        let reader = BufReader::new(stderr);
        for line in reader.lines() {
            if let Ok(line_content) = line {
                output_lines.push(line_content.clone());
                // 发送进度事件到前端
                window.emit_all("pip-progress", &line_content).unwrap();
                
                // 提取错误信息
                error_message.push_str(&line_content);
                error_message.push_str("\n");
            }
        }
    }
    
    // 等待命令完成
    let status = child.wait().map_err(|e| format!("Failed to wait for command: {}", e))?;
    let success = status.success();
    
    // 合并所有输出行
    let full_output = output_lines.join("\n");
    
    // 记录日志
    if let Err(err) = log_operation(
        &db.0,
        &operation_type,
        &package_spec,
        &full_command,
        success,
        &full_output,
        &error_message,
    ) {
        eprintln!("Failed to log operation: {}", err);
    }
    
    if success {
        Ok(full_output)
    } else {
        Err(format!("Command failed: {}", full_output))
    }
}

// 获取操作日志
#[tauri::command]
fn get_operation_logs(db: State<'_, DbConnection>) -> Result<Vec<OperationLog>, String> {
    let mut stmt = db.0.prepare("SELECT id, timestamp, operation_type, package_spec, command, success, output, error_message FROM operation_logs ORDER BY timestamp DESC")
        .map_err(|e| format!("Failed to prepare query: {}", e))?;
    
    let log_iter = stmt.query_map([], |row| {
        Ok(OperationLog {
            id: row.get(0)?,
            timestamp: row.get(1)?,
            operation_type: row.get(2)?,
            package_spec: row.get(3)?,
            command: row.get(4)?,
            success: row.get(5)?,
            output: row.get(6)?,
            error_message: row.get(7)?,
        })
    }).map_err(|e| format!("Failed to execute query: {}", e))?;
    
    let logs: Vec<OperationLog> = log_iter.collect::<Result<_, _>>()
        .map_err(|e| format!("Failed to collect logs: {}", e))?;
    
    Ok(logs)
}

fn main() {
    // 初始化数据库
    let conn = init_database().expect("Failed to initialize database");
    let db = DbConnection(Arc::new(conn));
    
    tauri::Builder::default()
        .manage(db)
        .invoke_handler(tauri::generate_handler![
            get_installed_packages,
            run_pip_command,
            get_operation_logs
        ])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}